/*
 * Copyright (C) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef IMAGE_KNIFE_C_KEKE_IMAGEKNIFE_NODE_IMAGE_H
#define IMAGE_KNIFE_C_KEKE_IMAGEKNIFE_NODE_IMAGE_H

#include "imageknife_node_internal.h"
namespace ImageKnifeC {

class ImageKnifeNodeImage : public ImageKnifeNodeInternal {
public:
    ImageKnifeNodeImage(std::string componentId, std::shared_ptr<ImageKnifeOption> option)
        : ImageKnifeNodeInternal(componentId, option, GetNodeAPI()->createNode(ARKUI_NODE_IMAGE))
    {
        onImageComplete_ = GetImageKnifeRequest()->GetImageKnifeOption()->onComplete;
        if (onImageComplete_ != nullptr) {
            GetNodeAPI()->registerNodeEvent(handle, NODE_IMAGE_ON_COMPLETE, 0, nullptr);
        }
    }

    ~ImageKnifeNodeImage() override
    {
        if (onImageComplete_ != nullptr) {
            GetNodeAPI()->unregisterNodeEvent(handle, NODE_IMAGE_ON_COMPLETE);
        }

        RemoveDisplayedImage();
    }

    bool Display(std::shared_ptr<ImageDataCacheInternal> data, bool isPlaceSrc) override
    {
        ArkUI_NodeAttributeType source = NODE_IMAGE_SRC;
        if (isPlaceSrc) {
            source = NODE_IMAGE_ALT;
        }

        if (data->GetDrawableDescriptor() != nullptr) {
            ArkUI_AttributeItem item = {.object = data->GetDrawableDescriptor()};
            GetNodeAPI()->setAttribute(handle, source, &item);
            return true;
        } else if (data->GetBase64() != nullptr) {
            ArkUI_AttributeItem item = {.string = data->GetBase64()};
            GetNodeAPI()->setAttribute(handle, source, &item);
            return true;
        }

        return false;
    }
    
    void FitImage(int fitEnum) override
    {
        imageFitEnum_.i32 = fitEnum;
        ArkUI_AttributeItem item = {.value = &imageFitEnum_, .size = 1};
        GetNodeAPI()->setAttribute(handle, NODE_IMAGE_OBJECT_FIT, &item);
    }
private:
    std::function<void(EventImage image)> onImageComplete_ = nullptr;

    // ImageFit, ArkUI_ObjectFit 枚举入参类型
    ArkUI_NumberValue imageFitEnum_ = {.i32 = 1};

    void OnDerivedNodeEvent(ArkUI_NodeEvent *event) override
    {
        auto eventType = OH_ArkUI_NodeEvent_GetEventType(event);
        switch (eventType) {
            case NODE_IMAGE_ON_COMPLETE:
                OnImageComplete(event);
                break;
            default: return;
        }
    }

    void OnImageComplete(ArkUI_NodeEvent *event)
    {
        enum ComponentDataIndex {
            LOADING_STATUS_INDEX = 0,
            WIDTH_INDEX,
            HEIGHT_INDEX,
            COMPONENT_WIDTH_INDEX,
            COMPONENT_HEIGHT_INDEX,
            CONTENT_OFFSET_X_INDEX,
            CONTENT_OFFSET_Y_INDEX,
            CONTENT_WIDTH_INDEX,
            CONTENT_HEIGHT_INDEX
        };

        if (onImageComplete_ != nullptr) {
            auto componentEvent = OH_ArkUI_NodeEvent_GetNodeComponentEvent(event);
            if (componentEvent->data[LOADING_STATUS_INDEX].i32 == 1) {
                // 在渲染完成时标记时间
                static_cast<ImageKnifeRequestInternal*>(GetImageKnifeRequest().get())->MarkDisplayEndTime();
            }

            onImageComplete_({.loadingStatus = componentEvent->data[LOADING_STATUS_INDEX].i32,
                              .width = componentEvent->data[WIDTH_INDEX].f32,
                              .height = componentEvent->data[HEIGHT_INDEX].f32,
                              .componentWidth = componentEvent->data[COMPONENT_WIDTH_INDEX].f32,
                              .componentHeight = componentEvent->data[COMPONENT_HEIGHT_INDEX].f32,
                              .contentOffsetX = componentEvent->data[CONTENT_OFFSET_X_INDEX].f32,
                              .contentOffsetY = componentEvent->data[CONTENT_OFFSET_Y_INDEX].f32,
                              .contentWidth = componentEvent->data[CONTENT_WIDTH_INDEX].f32,
                              .contentHeight = componentEvent->data[CONTENT_HEIGHT_INDEX].f32});
        }
    }

    void UpdateDerivedNodeEvent(std::shared_ptr<ImageKnifeOption> option) override
    {
        if (option->onComplete == nullptr && onImageComplete_ != nullptr) {
            // 避免遗漏事件反注册
            GetNodeAPI()->unregisterNodeEvent(handle, NODE_IMAGE_ON_COMPLETE);
        } else if (option->onComplete != nullptr && onImageComplete_ == nullptr) {
            // 旧的option没启用OnComplete  新的启用了，需注册事件
            GetNodeAPI()->registerNodeEvent(handle, NODE_IMAGE_ON_COMPLETE, 0, nullptr);
        }
        // 更新OnComplete 回调状态
        onImageComplete_ = option->onComplete;
    }

    void RemoveDisplayedImage() override
    {
        GetNodeAPI()->resetAttribute(handle, NODE_IMAGE_SRC);
    }

    bool IsAnimator() const override
    {
        return false;
    }
};

}

#endif // IMAGE_KNIFE_C_KEKE_IMAGEKNIFE_NODE_IMAGE_H
